﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Net.Forums
{
    using System;

    using Phuse.Mime;

    /// <summary>Represents an outbound forum article.</summary>
    /// <threadsafety static="true" instance="false"/>
    public interface IOutboundArticle
    {
        /// <summary>Gets the host this article is associated with.</summary>
        IHost Host
        {
            get;
        }

        /// <summary>Gets the date of the article last passed to <see cref="SaveMessage"/>.</summary>
        /// <value>The body of the Date header field, if the article has one; otherwise <c>null</c>.</value>
        DateTime? DateUtc
        {
            get;
        }

        /// <summary>Gets the subject of the article last passed to <see cref="SaveMessage"/>.</summary>
        /// <value>The body of the Subject header field, if the article has one; otherwise <c>null</c>.</value>
        string Subject
        {
            get;
        }

        /// <summary>Gets or sets the send status of the article.</summary>
        /// <exception cref="ArgumentException">Attempted to set to <see cref="M:SendStatus.Sent"/>.</exception>
        /// <exception cref="InvalidOperationException"><list type="bullet">
        /// <item>Set a value after <see cref="Cache.Dispose"/> has been called on the parent <see cref="Cache"/>
        /// object, or</item>
        /// <item>set a value after <see cref="IDeletablePersistentObject.Delete"/> has been called on the parent
        /// <see cref="IHost"/> object, or</item>
        /// <item>set a value after the message has already been sent.</item>
        /// </list></exception>
        SendStatus SendStatus
        {
            get;
            set;
        }

        /// <summary>Gets or sets a value indicating whether the article has been deleted.</summary>
        /// <exception cref="InvalidOperationException">Set a value after <see cref="Cache.Dispose"/> has been called
        /// on the parent <see cref="Cache"/> object, or, set a value after
        /// <see cref="IDeletablePersistentObject.Delete"/> has been called on the parent <see cref="IHost"/> object.
        /// </exception>
        bool IsDeleted
        {
            get;
            set;
        }

        /// <summary>Loads the message from the database.</summary>
        /// <returns>A copy of the message previously passed to <see cref="SaveMessage"/>, if <see cref="SaveMessage"/>
        /// has been called successfully before; otherwise, a default-constructed <see cref="Message"/> object.
        /// </returns>
        /// <exception cref="InvalidOperationException"><see cref="Cache.Dispose"/> has been called on the parent
        /// <see cref="Cache"/> object, or, <see cref="IDeletablePersistentObject.Delete"/> has been called on the
        /// parent <see cref="IHost"/> object.</exception>
        Message LoadMessage();

        /// <summary>Saves <paramref name="message"/> to the database.</summary>
        /// <exception cref="ArgumentNullException"><paramref name="message"/> equals <c>null</c>.</exception>
        /// <exception cref="InvalidOperationException"><list type="bullet">
        /// <item><see cref="Cache.Dispose"/> has been called on the parent <see cref="Cache"/> object, or</item>
        /// <item><see cref="IDeletablePersistentObject.Delete"/> has been called on the parent <see cref="IHost"/>
        /// object, or</item>
        /// <item>the message has already been sent, or</item>
        /// <item>a send/receive operation is in progress.</item>
        /// </list></exception>
        /// <remarks>
        /// <para>Each call to this method performs the following steps:</para>
        /// <list type="number">
        /// <item>Compares <paramref name="message"/> to the one currently stored in the database. If it differs,
        /// then the <see cref="Entity.MessageId"/> property of <paramref name="message"/> is set to a new unique
        /// value.</item>
        /// <item>Sets the <see cref="Entity.Date"/> property of <paramref name="message"/> to the current date.</item>
        /// </list>
        /// </remarks>
        void SaveMessage(Message message);
    }
}
